
// 实现更精准的类型提示和检查。
type ParseParam<Param extends string> = Param extends `${infer Key}=${infer Value}` ? {
    [K in Key]: Value
} : Record<string, any>

type MergeValues<One, Other> = One extends Other ? One : Other extends unknown[] ? [One, ...Other] : [One, Other]
type MergeParams<OneParam extends Record<string, any>, OtherParam extends Record<string, any>> = {
    readonly [Key in keyof OneParam | keyof OtherParam]: Key extends keyof OneParam ?
    Key extends keyof OtherParam ?
    MergeValues<OneParam[Key], OtherParam[Key]> : OneParam[Key] : Key extends keyof OtherParam ? OtherParam[Key] : never
}

type ParseQueryString<Str extends string> = Str extends `${infer Param}&${infer Rest}` ? MergeParams<ParseParam<Param>, ParseQueryString<Rest>> : ParseParam<Str>

function parseQueryString<Str extends string>(queryStr: Str): ParseQueryString<Str>

function parseQueryString(queryStr: string) {
    if (!queryStr || !queryStr.length) {
        return {}
    }
    const queryObj: Record<string, any> = {}
    const items = queryObj.split('&')
    items.forEach(item => {
        const [key, value] = item.split('=')
        if (queryObj[key]) {
            if (Array.isArray(queryObj[key])) {
                queryObj[key].push(value)
            } else {
                queryObj[key] = [queryObj[key], value]
            }
        } else {
            queryObj[key] = value
        }
    });
    return queryObj
}

const res = parseQueryString('a=1&b=2&c=3');

declare function ttt<T extends readonly unknown[] | []>(values:T) : T
const res1 = ttt([1,2,4])

interface PromiseConstructor {
    all<T extends readonly unknown[] | []>(values: T): Promise<{
        -readonly [P in keyof T]: Awaited<T[P]>
    }>
    race<T extends readonly unknown[] | []>(values: T): Promise<Awaited<T[number]>>
}
declare const promise: PromiseConstructor

const res2 = promise.all([1,2,3])
const res3 = promise.race([1,2,'a'])

// currying
type CurryiedFunc<Params, Return> = Params extends [infer Arg, ...infer Rest] ? (arg: Arg) => CurryiedFunc<Rest, Return> : never
declare function currying<Func>(fn: Func): Func extends (...args: infer Params) => infer Return ? CurryiedFunc<Params, Return> : never
const func = (a: number, b:number, c: boolean) => {}
const res4 = currying(func)

